require 'depac-common/softlayer'
require 'depac-deployment/environment_configuration'
require 'depac-deployment/helper'
require 'depac-deployment/configure'
require 'depac-deployment/provision'
require 'depac-deployment/update_ihsplugin'
require 'depac-common/constants'
require 'pp'

# Remove instances specified in inputConfigObject from an existing environment
def removeInstance(existingEnvConfigObject, inputConfigObject)

    
     #remove app node from IHS plugin configuration--add by cdl 20150121
     nodeInfoMap=appNodeToNodeInfoMap(inputConfigObject.getEnvironmentConfiguration(), Depac::CloudDeploymentConstants::RUNTIME_NODES)    
     if nodeInfoMap !=nil
         updateIHSPlugin_internal(nodeInfoMap, Depac::CloudDeploymentConstants::CLD_DPL_KEYPATH, inputConfigObject.getEnvironmentConfiguration(), "remove")  
     end
    
	runtimeNodes = inputConfigObject.getNodeConfigurationByType(Depac::CloudDeploymentConstants::RUNTIME_NODES)
	existingRuntimeNodes = existingEnvConfigObject.getNodeConfigurationByType(Depac::CloudDeploymentConstants::RUNTIME_NODES)
	deleted_count = 0
	runtimeNodes.each do |node|
		role = node[Depac::CloudDeploymentConstants::ROLE]
		count = node[Depac::CloudDeploymentConstants::NO_OF_NODES]
		node_info = node[Depac::CloudDeploymentConstants::NODE_INFO]
		#if node info isnt provided ,just delete the latest n nodes, 
		#eg for a count of 2 and existing nodes are 3 then node#2 and node#3 will be deleted
		node_info.each do |del_info|
			existingRuntimeNodes.each do |enode|
				if(enode[Depac::CloudDeploymentConstants::ROLE]==role)
					enode_info = enode[Depac::CloudDeploymentConstants::NODE_INFO]
					if(node_info!=nil)					
						objtodelete = nil
						enode_info.each do |info_obj|
							if(info_obj[Depac::CloudDeploymentConstants::HOSTNAME]==del_info[Depac::CloudDeploymentConstants::HOSTNAME])
								$slmgr.deleteInstance(info_obj[Depac::CloudDeploymentConstants::HOSTNAME])
								objtodelete=info_obj
								deleted_count+=1
							end
						end
					
						if(enode[Depac::CloudDeploymentConstants::ROLE]==Depac::CloudDeploymentConstants::ROLE_APPSERVER)
							enode[Depac::CloudDeploymentConstants::NO_OF_NODES]-=1
						else
							updateAgentIntgInfo(enode,objtodelete)
						end
						enode_info.delete(objtodelete)
					else
						for i in 1..count
							info_obj = enode_info.pop
							$slmgr.deleteInstance(info_obj[Depac::CloudDeploymentConstants::HOSTNAME])
							if(enode[Depac::CloudDeploymentConstants::ROLE]==Depac::CloudDeploymentConstants::ROLE_APPSERVER)
								enode[Depac::CloudDeploymentConstants::NO_OF_NODES]-=1
								deleted_count+=1
							else
								updateAgentIntgInfo(enode,info_obj)
							end
						end
					end				
				end
			end		
		end	
	end
	Depac::Log.write("INFO", "'#{deleted_count}' instances deleted ")
	return existingEnvConfigObject
end

# Validate remove instance configuration
# following same convention as addinstance, removal of db/jms nodes not permitted.
def validateRemoveInstanceConfiguration(existingEnvConfigObject, inputConfigObject)
	runtimeNodes = inputConfigObject.getNodeConfigurationByType(Depac::CloudDeploymentConstants::RUNTIME_NODES)
	existingRuntimeNodes = existingEnvConfigObject.getNodeConfigurationByType(Depac::CloudDeploymentConstants::RUNTIME_NODES)

	# validation 1 - removal of database nodes
	if(inputConfigObject.getDatabaseConfigurationByType(Depac::CloudDeploymentConstants::RUNTIME_NODES) != nil)
		Depac::Log.write("ERROR", "Removal of a database instance is not supported.")
		exit 3
	end
	
	# validation 2 - removal of jms nodes
	if(inputConfigObject.getNodeConfigurationByRoleAndType(Depac::CloudDeploymentConstants::ROLE_JMS, Depac::CloudDeploymentConstants::RUNTIME_NODES) != nil)
		Depac::Log.write("ERROR", "Removal of a jms instance is not supported.")
		exit 3
	end
	# validation 3 - check if the number of nodes to be removed doesnt exceed existing nodes. 
	runtimeNodes.each do |node|
		role = node[Depac::CloudDeploymentConstants::ROLE]
		count = node[Depac::CloudDeploymentConstants::NO_OF_NODES]
		existingRuntimeNodes.each do |enode|
			existing_node_count= enode[Depac::CloudDeploymentConstants::NO_OF_NODES]
			if(existing_node_count==nil)
				existing_node_count = enode[Depac::CloudDeploymentConstants::NODE_INFO].length
			end	
			if(enode[Depac::CloudDeploymentConstants::ROLE]==role and existing_node_count<count)
				Depac::Log.write("ERROR", "The number of nodes to be removed exceed number of existing nodes for role '#{role}'")
				exit 3
			end
		end
	end
end

# Remove instances specified in inputConfigObject from an existing environment
def removeInstance_upateEnv(existingEnvConfigObject, inputConfigObject, updSequence)
    
	runtimeNodes = inputConfigObject.getNodeConfigurationByType(Depac::CloudDeploymentConstants::RUNTIME_NODES)
	existingRuntimeNodes = existingEnvConfigObject.getNodeConfigurationByType(Depac::CloudDeploymentConstants::RUNTIME_NODES)
	deleted_count = 0
	runtimeNodes.each do |node|
		role = node[Depac::CloudDeploymentConstants::ROLE]
		count = node[Depac::CloudDeploymentConstants::NO_OF_NODES]
		node_info = node[Depac::CloudDeploymentConstants::NODE_INFO]             
              
        isUpdated=false

        updSequence.each do |seqrole|
            if seqrole['role'] == role 
                 isUpdated = true
                 break
            end 
        end

        if role != Depac::CloudDeploymentConstants::ROLE_DATABASE and role != Depac::CloudDeploymentConstants::ROLE_JMS and isUpdated

              
		#if node info isnt provided ,just delete the latest n nodes, 
		#eg for a count of 2 and existing nodes are 3 then node#2 and node#3 will be deleted
		node_info.each do |del_info|
			existingRuntimeNodes.each do |enode|
				if(enode[Depac::CloudDeploymentConstants::ROLE]==role)
					enode_info = enode[Depac::CloudDeploymentConstants::NODE_INFO]                                                           

					if(node_info!=nil)					
						enode_info.each do |info_obj|
							if(info_obj[Depac::CloudDeploymentConstants::HOSTNAME]==del_info[Depac::CloudDeploymentConstants::HOSTNAME])
                                Depac::Log.write("INFO", "delete  #{del_info['IP']}.............")
                                begin
									$slmgr.deleteInstance(del_info[Depac::CloudDeploymentConstants::HOSTNAME])
								rescue Timeout::Error => e
									Depac::Log.write("INFO", "Timeout Error occurred while trying to delete, please manually delete the instance with ip - #{del_info['IP']} and hostname - #{del_info[Depac::CloudDeploymentConstants::HOSTNAME]} .")
								end
								deleted_count+=1      
							end
						end
						
                        if(enode[Depac::CloudDeploymentConstants::ROLE]==Depac::CloudDeploymentConstants::ROLE_APPSERVER)
							enode[Depac::CloudDeploymentConstants::NO_OF_NODES]-=1
						else
							updateAgentIntgInfo(enode,del_info)
						end                      
						enode_info.delete(del_info)
				     end				
				end
			end		
		end
           end	
	end
	Depac::Log.write("INFO", "'#{deleted_count}' instances deleted ")
	return existingEnvConfigObject
end

def updateAgentIntgInfo(nodeObj , deletedNode)
	serverNameArr=nil
	if(nodeObj[Depac::CloudDeploymentConstants::ROLE] == Depac::CloudDeploymentConstants::ROLE_AGENT)
		serverNameArr = nodeObj[Depac::CloudDeploymentConstants::AGENT_NODES]		
	elsif(nodeObj[Depac::CloudDeploymentConstants::ROLE] == Depac::CloudDeploymentConstants::ROLE_INTG)		
		serverNameArr = nodeObj[Depac::CloudDeploymentConstants::INTG_NODES]		
	end
	serverNametoDel = nil
	serverNameArr.each do |serverName|
		if(serverName["server_name"]==deletedNode["info"])
			serverNametoDel=serverName
		end
	end
	serverNameArr.delete(serverNametoDel)		
end